﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OOLib
{
   /// <summary>
   /// A text document is a model component which contains text structured by paragraphs. 
   /// Each paragraph and each portion of text can be fitted with some attributes (technically properties).
   /// Its declared as generic text document, because its function is needed by different derived services (TextDocument/WebDocument/GlobalDocument).
   /// In addition, all text objects can be searched.
   /// </summary>
   public class TextDocument : OfficeDocument, IBookmarksSupplier, IMultiServiceFactory
   {
      #region Constructors

      /// <summary>
      /// Constructor
      /// </summary>
      /// <remarks>
      /// After using this constructor, the ComObj must be set manually!
      /// </remarks>
      public TextDocument() :
         base()
      {
         _MultiServiceFactoryImpl = new MultiServiceFactoryImpl(this);
      }

      /// <summary>
      /// Constructor
      /// </summary>
      /// <param name="comObject">COM object</param>
      public TextDocument(object comObject) :
         base(comObject)
      {
         _MultiServiceFactoryImpl = new MultiServiceFactoryImpl(this);
      }

      #endregion

      #region IMultiServiceFactory

      private MultiServiceFactoryImpl _MultiServiceFactoryImpl;

      /// <summary>
      /// Creates an instance classified by the specified name.
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance.</param>
      /// <returns>Returns a new instance.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public object CreateInstance(string serviceSpecifier)
      {
         CheckDisposed();
         return _MultiServiceFactoryImpl.CreateInstance(serviceSpecifier);
      }

      /// <summary>
      /// Creates an instance classified by the specified name and passes the arguments to that instance.
      /// </summary>
      /// <param name="serviceSpecifier">Classified name of instance.</param>
      /// <param name="arguments">Arguments passed to the instance.</param>
      /// <returns>Returns a new instance.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public object CreateInstanceWithArguments(string serviceSpecifier, object[] arguments)
      {
         CheckDisposed();
         return _MultiServiceFactoryImpl.CreateInstanceWithArguments(serviceSpecifier, arguments);
      }

      /// <summary>
      /// Provides the available names of the factory to be used to create instances.
      /// </summary>
      /// <returns>Returns an array of all names.</returns>
      /// <remarks>!!! Not tested !!!</remarks>
      public string[] GetAvailableServiceNames()
      {
         CheckDisposed();
         return _MultiServiceFactoryImpl.GetAvailableServiceNames();
      }

      #endregion

      #region XTextDocument

      /// <summary>
      /// Gets the major Text of the text document.
      /// </summary>
      public Text Text
      {
         get 
         {
            CheckDisposed();
            return GetObjectWrapper<Text>(InvokeMethod("getText"));
         }
      }

      /// <summary>
      /// Reformats the contents of the document. 
      /// </summary>
      /// <remarks>!!! Not tested !!!</remarks>
      public void Reformat()
      {
         CheckDisposed();
         InvokeMethod("reformat");
      }

      #endregion

      #region GenericTextDocument properties
      //todo implement properties
      #endregion

      #region IBookmarksSupplier
      
      /// <summary>
      /// Gets the collection of all bookmarks associated with a data source.
      /// </summary>
      /// <remarks>
      /// A bookmark is simply a string specifying the location of the bookmarked document.
      /// </remarks>
      public NameAccess<Bookmark> Bookmarks 
      { 
         get
         {
            CheckDisposed();
            return GetObjectWrapper<NameAccess<Bookmark>>(InvokeMethod("getBookmarks"));
         }
      }

      #endregion

      #region utility methods

      /// <summary>
      /// Replaces the content of a bookmark.
      /// </summary>
      /// <param name="name">Name of the bookmark.</param>
      /// <param name="str">String which replaces the bokkmark content.</param>
      /// <remarks>!!! Not tested !!!</remarks>
      public void ReplaceBookmark(string name, string str)
      {
         CheckDisposed();

         var bookmark = Bookmarks[name];
         if (bookmark == null)
         {
            throw new KeyNotFoundException(String.Format("The bookmark '{0}' does not exist", name));
         }
         var textCursor = Text.CreateTextCursorByRange(bookmark.GetAnchor());
         if (textCursor == null)
         {
            throw new ApplicationException("Failed to get TextCursor from Bookmark");
         }
         textCursor.String = str;
      }

      // Kopiert den inhalt eines Bookmarks (mit formatierungen)
      /// <summary>
      /// Copies the content of a bookmark.
      /// </summary>
      /// <param name="name">Name of the bookmark.</param>
      /// <param name="targetRange">Target text range. If null, the bookmark text range is taken as target.</param>
      /// <returns>return the target text range.</returns>
      public object CopyBookmarkContent(string name, TextRange targetRange)
      {
         CheckDisposed();

         var bookmark = Bookmarks[name];
         if (bookmark == null)
         {
            throw new KeyNotFoundException(String.Format("The bookmark '{0}' does not exist", name));
         }
         var sourceRange = bookmark.GetAnchor();
         if (targetRange == null)
         {
            targetRange = sourceRange;
         }
         return Copy(sourceRange, targetRange);
      }
      
      /// <summary>
      /// Creates a new text section.
      /// </summary>
      /// <param name="name">Name of the text section.</param>
      /// <returns>Returns the new text section.</returns>
      public TextSection CreateTextSection(string name = null)
      {
         CheckDisposed();

         var ts = new TextSection(CreateInstance("com.sun.star.text.TextSection"));
         if (name != null)
         {
            ts.Name = name;
         }
         return ts;
      }

      /// <summary>
      /// Creates a new bookmark, without adding it to the text.
      /// </summary>
      /// <param name="name">Name of the bookmark.</param>
      /// <returns>Returns the new bookmark.</returns>
      public Bookmark CreateBookmark(string name = null)
      {
         CheckDisposed();

         var bm = new Bookmark(CreateInstance("com.sun.star.text.Bookmark"));
         if (name != null)
         {
            bm.Name = name;
         }
         return bm;
      }

      /// <summary>
      /// Adds a new Bookmark to the text.
      /// </summary>
      /// <param name="name">Name of the bookmark.</param>
      /// <param name="content">Content for the new Bookmark. Can be null.</param>
      /// <param name="absorbContent">true if the content should be absorbed.</param>
      /// <returns>Returns the new bookmark.</returns>
      public Bookmark AddBookmarkToText(string name, TextRange content, bool absorbContent = true)
      {
         CheckDisposed();

         var bm = CreateBookmark(name);

         if (content != null)
         {
            Text.InsertTextContent(content, bm, absorbContent);
         }
         return bm;
      }

      // Kopiert den Inhalt mit Formatierung
      /// <summary>
      /// Copies source range to target range with all formatings
      /// </summary>
      /// <param name="source">Source text ranghe</param>
      /// <param name="target">Target text range</param>
      /// <returns>Returns the target text range.</returns>
      /// <remarks>
      /// This method does not use the clipboard!
      /// </remarks>
      public TextRange Copy(TextRange source, TextRange target)
      {
         CheckDisposed();

         var bookmark = AddBookmarkToText("__CopyBookmark", source);         

         var section = CreateTextSection("__CopySection");
         var fileLink = section.FileLink;
         fileLink.FileURL = Url;
         section.LinkRegion = "__CopyBookmark";
         section.Attach(target);

         // remove source bookmark and destination section
         Text.RemoveTextContent(bookmark);
         Text.RemoveTextContent(section);

         return target;
      }

      /*
            // Kopiert den inhalt eines Bookmarks (mit formatierungen)
            public object CopyBookmarkContent(string name, string targetBookmark, bool afterBookmark)
            {
      
            }

            // erzeugt ein neues Bookmark
            public object CreateBookmark(object textCursor, string bookmarkName)
            {
      
            }

            // Löscht das Bookmark (nicht den Inhalt)
            public void RemoveBookmark(string name)
            {
      
            }

            // Löscht ein TextContent (nicht den Inhalt)
            public void RemoveTextContent(object content)
            {
      
            }

            // Fügt einen Seitenumbruch ein
            public object InsertPageBreak(object cursor)
            {
      
            }

            // Fücgt ein ControlChar ein (0=PARAGRAPH_BREAK, )
            public object InsertControlChar(object cursor, int chracter, bool afterCursor)
            {
      
            }

            // Aktualisiert alle Verzeichnisse
            public void RefreshIndexes()
            {
      
            }

            // Gibt die Seitennummer des TextCursors an 
            public int GetPageNumberFromTextCursor(object cursor)
            {
      
            }

            // Kopiert einen TextCursor
            public object CopyTextCursor(object cursor)
            {
      
            }

            // Ersetzt den Inhalt eines Bookmarks mit ein Graphic aus Datei
            // bring kein Fehler aber macht auch nichts
            public object InsertImage(object cursor, string fileName)
            {
      
            }

            // Ersetzt den Inhalt eines Dumy-Graphic mit ein Graphic aus Datei
            public object InsertImageIntoDumyImage(string dummyImageName, string fileName)
            {
      
            }

            // ClipBoard einfügen über Macro , fügt alles ein 
            public void PasteClipboardOverMacro(object cursor)
            {
      
            }

            // ClipBoard einfügen direkt , nur für Strings  und UnicodeFormat 
            public void PasteClipboardDirect(string bookmarkName)
            {
      
            }

            // CreateUnoService
            public object CreateUnoService(string serviceName)
            {
      
            }

            // TextTabelle einfügen
            public void InsertTextTable(object cursor, string tableName, int cols, int rows, int leftMargin, int rightMargin)
            {
      
            }
    
            // Tabelle einstellen über die gesamte Tabelle.
            // Für die Lieneneinstellung gilt das Selbe wie für Zellen.
            // Nur das es noch zwei weitere Linien gibt die horizontalen und vertikalen.
            // ( Horizontalline,Verticalline).
            public void SetTextTableBorder(string tableName, string color, int borderDist)
            {
      
            }

            // set value in eine Zelle in TextTable
            public void SetCellValueInTextTable(string tableName, int row, int col, string value)
            {
      
            }

            public void SetFormat(string value)
            {
      
            }

            public void SetFormat_CellRange(string tableName, int left, int top, int right, int bottom)
            {
      
            }*/
      #endregion
   }
}
